package managers.dateManager.endFrozen.resourceChange;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.tbjd.client.beans.Resource;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.exceptions.DateManagerException;
import org.tbjd.client.managers.TaskManager;
import org.tbjd.client.states.StateEndFrozenSPEC;

import factories.ResourceFactory;
import factories.TaskFactory;

/**
 * <p>
 * Test TaskManager's methods
 * </p>
 * <p>
 * <b>Case</b>
 * </p>
 * <p>
 * Task with EndDate frozen and no relationships (predecessors/successors)
 * </p>
 * <p>
 * <b>Action</b>
 * </p>
 * <p>
 * Change ratio of the task "task"
 * </p>
 * <p>
 * <b> Expected</b>
 * <ul>
 * <li>update BeginDate</li>
 * <li>update Duration</li>
 * </ul>
 * </p>
 * 
 * @author Michael Martin
 * @author Antonio Carrozzini
 * @version 1.0
 */
public class EndFrozen_ResourceChange_SingleTask_Basic extends TestCase {

	private Task task = null;
	private Map<Integer, Object> map = null;
	private Logger log = Logger.getLogger("console");
	private DateFormat df = DateFormat.getInstance();
	private TaskManager dateManager = new TaskManager();

	protected void setUp() throws Exception {
		df = new SimpleDateFormat("dd.MM.yyyy");

		this.task = (Task) TaskFactory.getInstance();
		this.task.setState(new StateEndFrozenSPEC(task.getState().getDurationModeState()));

		Resource resource = ResourceFactory.getInstance();
		resource.addTask(this.task);

		super.setUp();
	}

	public void testListNullity() {
		System.out.println("");
		log.debug(" === testListNullity");

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call TaskManager...");
		try {
			assertNotNull("Updated bean list isn't null", dateManager.manageDates(map));

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

	}

	public void testListSize() {
		System.out.println("");
		log.debug(" === testListSize");

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}
		assertEquals(1, updatedBeans.size());

	}

	public void testInstanceEquality() {
		System.out.println("");
		log.debug(" === testInstanceEquality");

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(this.task, updatedBeans.get(0));

	}

	public void testDurationsChangeRatio() {
		System.out.println("");
		log.debug(" === testDurationsChangeRatio");

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(48f, updatedBeans.get(0).getDuration());

	}

	public void testDurationsAddResource() {
		System.out.println("");
		log.debug(" === testDurationsAddResource");

		Resource newResource = ResourceFactory.getInstance();
		this.task.addResource(newResource);
		log.debug("new Resource = " + newResource);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newResource);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(12f, updatedBeans.get(0).getDuration());

	}

	public void testDatesChangeRatio() {
		System.out.println("");
		log.debug(" === testDatesChangeRatio");

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		try {
			assertEquals(df.parseObject("31.5.2009"), updatedBeans.get(0).getBeginDate());
			assertEquals(df.parseObject("2.6.2009"), updatedBeans.get(0).getEndDate());

		} catch (ParseException e) {
			fail(e.getMessage());

		}

	}

	public void testDatesAddResource() {
		System.out.println("");
		log.debug(" === testDatesAddResource");

		Resource newResource = ResourceFactory.getInstance();
		this.task.addResource(newResource);
		this.task.setEffort(48f);
		this.task.setDuration(48f);
		try {
			this.task.setEndDate(df.parse("3.6.2009"));
			
		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}
		log.debug("new resource = " + newResource);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newResource);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		try {
			assertEquals(df.parseObject("2.6.2009"), updatedBeans.get(0).getBeginDate());
			assertEquals(df.parseObject("3.6.2009"), updatedBeans.get(0).getEndDate());

		} catch (ParseException e) {
			fail(e.getMessage());

		}

	}

	public void testRevertDurations() {
		System.out.println("");
		log.debug(" === testRevertDurations");

		float originalDuration = task.getDuration();
		int oldRatio = task.getResources().get(0).getRatio();

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original Duration...");
		this.task.getResources().get(0).setRatio(oldRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, oldRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved Duration = " + updatedBeans.get(0).getDuration() + " & original Duration = " + originalDuration);
		assertEquals(originalDuration, updatedBeans.get(0).getDuration());

	}

	public void testRevertDates() {
		System.out.println("");
		log.debug(" === testRevertDates");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		int originalRatio = task.getResources().get(0).getRatio();

		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original Duration...");
		this.task.getResources().get(0).setRatio(originalRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved BeginDate = " + updatedBeans.get(0).getBeginDate() + " & original BeginDate = " + originalBeginDate);
		assertEquals(originalBeginDate, updatedBeans.get(0).getBeginDate());
		assertEquals(originalEndDate, updatedBeans.get(0).getEndDate());

	}
	
	public void testRevertChainingModes() {
		System.out.println("");
		log.debug(" === testRevertChainingModes");

		boolean originalChainingMode = task.getState().isASAPChainingMode();
		int originalRatio = task.getResources().get(0).getRatio();
		int newRatio = 50;
		this.task.getResources().get(0).setRatio(newRatio);
		log.debug("new Ratio = " + newRatio);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, newRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original Duration...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_resource, originalRatio);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		assertEquals(originalChainingMode, updatedBeans.get(0).getState().isASAPChainingMode());

	}

}